import functools
import logging
import streamlit as st
from functools import lru_cache

# 配置日志记录
logging.basicConfig(
    level=logging.WARNING,
    format="%(asctime)s - %(levelname)s - %(message)s",
    filename="app.log",  # 指定日志文件路径
    filemode="a",  # 追加模式，如果需要覆盖则使用 'w'
)


class FunctionExecutionError(Exception):
    def __init__(self, message):
        super().__init__(f"An unexpected error occurred in function: {message}")


@lru_cache(maxsize=128)
def exception_handler(func):
    """
    一个装饰器，用于处理函数中的异常。
    使用此装饰器可以捕获被装饰函数在执行过程中抛出的异常，
    并在控制台和Streamlit应用中打印错误信息。

    参数:
    - func: 被装饰的函数。

    返回:
    - wrapper函数，它会尝试执行被装饰的函数并处理其中的异常。
    """

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        try:
            # 尝试执行被装饰的函数
            return func(*args, **kwargs)
        except ValueError as ve:
            # 捕获特定的ValueError
            safe_error_message = "A ValueError occurred in function '{}': {}".format(
                func.__name__, str(ve)
            )
            print(safe_error_message)
            logging.error(safe_error_message)
            st.error("Error happened! 请联系管理员！", icon="🚨")
            raise FunctionExecutionError(safe_error_message)
        except TypeError as te:
            # 捕获特定的TypeError
            safe_error_message = "A TypeError occurred in function '{}': {}".format(
                func.__name__, str(te)
            )
            print(safe_error_message)
            logging.error(safe_error_message)
            st.error("Error happened! 请联系管理员！", icon="🚨")
            raise FunctionExecutionError(safe_error_message)
        except Exception as e:
            # 捕获其他所有异常
            safe_error_message = (
                "An unexpected error occurred in function '{}': {}".format(
                    func.__name__, str(e)
                )
            )
            print(safe_error_message)
            logging.error(safe_error_message)
            st.error("Error happened! 请联系管理员！", icon="🚨")
            raise FunctionExecutionError(safe_error_message)

    return wrapper
